// Tags: DP, Tree
#include <algorithm>
#include <cstdio>

const int N = 2e5 + 5, mod = 1e4 + 7;
int n, ans, max, f[N], w[N], g[N];
int e_cnt, heads[N];

struct Edge {
  int v, nxt;
} e[N << 1];

inline void add(int u, int v) {
  e[++e_cnt].v = v, e[e_cnt].nxt = heads[u], heads[u] = e_cnt;
}

void solve(int x, int fa) {
  for (int i = heads[x], v; i; i = e[i].nxt) {
    if ((v = e[i].v) != fa) {
      solve(v, x);
      ans += f[v] * w[x] % mod;
      max = std::max(max, g[v] * w[x]);
      if (ans >= mod) ans -= mod;

      ans += f[x] * w[v] % mod;
      max = std::max(max, w[v] * g[x]);
      if (ans >= mod) ans -= mod;

      f[x] += w[v];
      if (f[x] >= mod) f[x] -= mod;
      g[x] = std::max(g[x], w[v]);
    }
  }
}

int main() {
#ifndef ONLINE_JUDGE
#ifdef LOCAL
  freopen("testdata.in", "r", stdin);
  freopen("testdata.out", "w", stdout);
#else
  freopen("P1351 联合权值.in", "r", stdin);
  freopen("P1351 联合权值.out", "w", stdout);
#endif
#endif

  scanf("%d", &n);
  for (int i = 1, u, v; i < n; ++i) {
    scanf("%d%d", &u, &v);
    add(u, v), add(v, u);
  }
  for (int i = 1; i <= n; ++i) scanf("%d", &w[i]);
  solve(1, 1);
  printf("%d %d", max, (ans << 1) % mod);
  return 0;
}